
#ifndef __statemachineH__
#define __statemachineH__

#include "kernel.h"

namespace WtfEngine {
	template <class tState>
	class StateMachine;

	/**
	 * Custom state class - registers with its base AppState to receive
	 * all its events, which are forwarded into the state's own event
	 * channels when the state is active.
	 **/
	class State: public virtual IAppState, public EventChannel {
		// Functor must not reference this object - we want it to
		// be deleted so it can remove its handler from its parent's event
		// channel
		typedef ObjFunctor<WeakRef<State> > tFunctor;
		
		IAppState::tRef mrParent;

	public:
		State(IAppState::tRefa rParent)
			: EventChannel(new Event()), mrParent(rParent)
		{
			mrParent->BindEvent(new Event(),
				EventHandler(new tFunctor(this, &State::OnEvent),
				EventHandler::PRIO_GAME_CRITICAL));
		};
		
		virtual ~State() {
			mrParent->RemoveHandler(new ObjFunctor<State>(this, &State::OnEvent));
		};

		void OnEvent() {
			Event::tEventStatus status;
			ProcessEvent(Kernel::GetInstance().GetCurrentEvent<Event>(), status);
			Kernel::GetInstance().SetEventStatus(status);
		};

		inline tGameTime GetTime() const {
			return mrParent->GetTime();
		};
		inline tGameTime GetDelta() const {
			return mrParent->GetDelta(); 
		};

	protected:
		template <class tState>
		static inline void SetState(StateMachine<tState> *pStateMachine, tState *pState) {
			pStateMachine->SetState(pState);
		};

		GC_AUTOSIZE(State);
	};

	template <class tState>
	class StateMachine {
	protected:
		typedef typename Meta::ClassTraits<tState>::tPtr tStateRef;
		tStateRef mrState;

		inline typename Meta::ValueTraits<tStateRef>::tConstRef getState() const {
			return mrState;
		};
		inline void SetState(typename Meta::ValueTraits<tStateRef>::tConstRef rState) {
			mrState = rState;
		};

		friend class State;
	};

};

#endif
